#pragma once

#include <vector>
#include <atlstr.h>

namespace FusionWare
{
    namespace MSI
    {
       //exception type for MSI errors
       class Exception
       {
       public:
           CString Msg;
           UINT Error;

           Exception(const TCHAR* Msg, UINT Error) 
               : Msg(Msg)
               , Error(Error)
           {
           }
       };
       static const std::bad_alloc OutOfMemory;
       
       class Session
       {
           MSIHANDLE hInstall;

       public:
           Session(MSIHANDLE hInstall = NULL) : hInstall(hInstall) {};

           void LogMsg(const TCHAR* Msg, bool ThrowOnFail=true);
           void LogMsg(_bstr_t Msg, bool ThrowOnFail=true);

           ////////////////////////////////////////////////////////////
           // Description:
           //   Pretireves and parse the CustomActionData to a vector
           //
           // Input:
           //   MinArgs    - [Default=0] Minumum number of arguments
           //   pDelimiter - [Default=_T(";")] Delimiter between args in the CustomActionData string
           //
           // Returns:
           //   Vector of strings one arg per entry.
           // 
           // Remarks:
           //   The arguments are provided in the MSI CustomActionData
           //   property. They *MUST* be formatted with the delimiter.
           //   This function will retrieve the data as a single string
           //   then parse it into the individual sub strings.
           //
           //   If MinArgs is greater then the total number of arguments
           //   parsed this method will throw an exception.
           //
           std::vector<CString> GetCustomActionData(unsigned MinArgs=0, const TCHAR* pDelimiter=_T(";"));

           ////////////////////////////////////////////////////////////
           // Description:
           //   Delegate for processing a deferred custom action
           //
           // Remarks:
           //   Functions implementing this signature should throw an
           //   MSI::Exception on errors
           //
           typedef void (*CaFunc)(Session& Session);

           ////////////////////////////////////////////////////////////
           // Description:
           //   Process a single action
           //
           // Returns:
           //   MSI error/Status code
           //
           // Remarks:
           //   Process a single Custom action by calling the provided
           //   Action function in a try/catch block to translate
           //   exceptions to proper return codes for MSI
           //   
           UINT DoCustomAction(CaFunc Action);

           ////////////////////////////////////////////////////////////
           // Description:
           //   Get the value of a property from this session
           //
           // Returns:
           //   String value of the property
           //
           CString GetProperty(const TCHAR* Name);
       };
    }
}
